# -*- coding: utf-8 -*-
# @File     : api.py
# @Author   : bingjia
# @Time     : 2020/8/5 18:29
# @Desc     : 项目api

import time
import json
from xpinyin import Pinyin
from django.apps import apps
from django.http import HttpResponse
from django.contrib.auth import get_user_model
from django.utils.translation import ugettext_lazy as _
from django.shortcuts import get_object_or_404, get_list_or_404

from ..base.api import viewsets
from ..base.api import response
from ..base.api import exceptions as exc
from ..base.utils.parse_data import parse_data
from ..base.api.utils.decorators import detail_route

from . import models
from . import signals
from . import services
from . import validators
from . import permissions
from . import serializers


class RoleViewSet(viewsets.ModelViewSet):
    """
    角色视图
    """
    queryset = models.Role
    "验证"
    validator_class = validators.RoleValidator
    "序列化"
    serializer_class = serializers.RoleSerializer
    "权限"
    permission_classes = (permissions.RolePermission,)

    def _part_save_role(self, name: str, project_id: int, permissions: list, slug: str):
        """
        部分保存项目
        """
        is_exist, reason = services.is_role_already_exist(name, project_id)
        if is_exist:
            raise exc.ValidationError(reason)

        role_model = models.Role
        role = role_model(
            name=name,
            slug=slug,
            permissions=permissions,
            project=models.Project.objects.get(pk=project_id)
        )
        try:
            role.save()
        except Exception as e:
            raise exc.ValidationError(_("membership add failed"))

        signals.role_registered_signal.send(sender=role.__class__, project=role)

        return role

    def list(self, request, *args, **kwargs):
        """
        群查(角色)
        """
        resource_id = kwargs.get("resource_id", None)
        project_object = get_object_or_404(models.Project.objects.all(), pk=resource_id)

        self.check_permissions(request, 'list', project_object)

        role_object_list = get_list_or_404(self.get_queryset(), project=project_object)
        if role_object_list:
            page = self.paginate_queryset(role_object_list)
            if page is not None:
                serializer = self.get_serializer(page, many=True)
                return self.get_paginated_response(serializer.data)
            else:
                serializer = self.get_serializer(role_object_list, many=True)

            return response.Ok(serializer.data)
        else:
            return response.Ok({"message": "Have no role"})

    def create(self, request, *args, **kwargs):
        """
        添加(角色)
        """
        resource_id = kwargs.get("resource_id", None)
        project_object = get_object_or_404(models.Project.objects.all(), pk=resource_id)

        self.check_permissions(request, 'create', project_object)
        "验证数据"
        try:
            data = parse_data(request.data, cls=validators.RoleValidator)
            role = self._part_save_role(**data)
        except exc.ParseError as e:
            raise exc.BadRequest(e.detail)

        serializer = self.get_serializer(role)
        return response.Created(serializer.data)

    def destroy(self, request, *args, **kwargs):
        """
        删除(角色)
        """
        role_object = get_object_or_404(self.get_queryset(), pk=kwargs["pk"])
        self.check_permissions(request, 'destroy', role_object)
        role_object.delete()
        return response.NoContent()

    def partial_update(self, request, *args, **kwargs):
        """
        更新(角色)
        """
        role = get_object_or_404(self.get_queryset(), pk=kwargs["pk"])
        self.check_permissions(request, 'partial_update', role)

        if "permissions" in request.data:
            role.permissions = request.data["permissions"]

        try:
            role.save()
        except Exception as e:
            raise exc.ValidationError(_("role add failed"))

        serializer = self.get_serializer(role)
        return response.Ok(serializer.data)


class MembershipViewSet(viewsets.ModelViewSet):
    """
    团队视图
    """
    queryset = models.Membership
    "验证"
    validator_class = validators.MembershipValidator
    "序列化"
    serializer_class = serializers.MembershipSerializer
    "权限"
    permission_classes = (permissions.MembershipPermission,)

    def _save_membership(self, full_name: str, project_id: int, role: int, is_admin=False):
        """
        部分保存项目
        """
        is_exist, reason = services.is_membership_already_exist(full_name, project_id, role)
        if is_exist:
            raise exc.ValidationError(reason)

        membership_model = models.Membership
        membership = membership_model(
            is_admin=is_admin,
            role=models.Role.objects.get(name=role),
            user=get_user_model().objects.get(full_name=full_name),
            project=models.Project.objects.get(pk=project_id)
        )
        try:
            membership.save()
        except Exception as e:
            raise exc.ValidationError(_("membership add failed"))

        signals.project_registered_signal.send(sender=membership.__class__, project=membership)

        return membership

    def list(self, request, *args, **kwargs):
        """
        群查(团队)
        """
        resource_id = kwargs.get("resource_id", None)
        project_object = get_object_or_404(models.Project.objects.all(), pk=resource_id)

        self.check_permissions(request, 'list', project_object)

        membership_object_list = get_list_or_404(self.get_queryset(), project=project_object)
        if membership_object_list:
            page = self.paginate_queryset(membership_object_list)
            if page is not None:
                serializer = self.get_serializer(page, many=True)
                return self.get_paginated_response(serializer.data)
            else:
                serializer = self.get_serializer(membership_object_list, many=True)

            return response.Ok(serializer.data)
        else:
            return response.Ok({"message": "Have no membership"})

    def create(self, request, *args, **kwargs):
        """
        添加成员
        """
        resource_id = kwargs.get("resource_id", None)
        project_object = get_object_or_404(models.Project.objects.all(), pk=resource_id)

        self.check_permissions(request, 'create', project_object)

        "验证数据"
        try:
            data = parse_data(request.data, cls=validators.MembershipValidator)
            membership = self._save_membership(**data)
        except exc.ParseError as e:
            raise exc.BadRequest(e.detail)

        serializer = self.get_serializer(membership)

        return response.Created(serializer.data)

    def partial_update(self, request, *args, **kwargs):
        """
        更新成员
        """
        membership = get_object_or_404(self.get_queryset(), pk=kwargs["pk"])
        self.check_permissions(request, 'partial_update', membership)

        if "is_admin" in request.data:
            membership.is_admin = request.data["is_admin"]

        if "role_id" in request.data:
            membership.role = models.Role.objects.get(pk=request.data["role_id"])

        try:
            membership.save()
        except Exception as e:
            raise exc.ValidationError(_("membership add failed"))

        serializer = self.get_serializer(membership)
        return response.Ok(serializer.data)

    def destroy(self, request, *args, **kwargs):
        """
        删除成员
        """
        membership_object = get_object_or_404(self.get_queryset(), pk=kwargs["pk"])
        self.check_permissions(request, 'destroy', membership_object)
        membership_object.delete()
        return response.NoContent()


class ProjectViewSet(viewsets.ModelViewSet):
    """
    项目视图
    """
    queryset = models.Project.objects.all()
    "验证"
    validator_class = validators.ProjectValidator
    "序列化"
    serializer_class = serializers.ProjectSerializer
    "权限"
    permission_classes = (permissions.ProjectPermission,)

    def _save_project(self, request, name: str, company: str, operation_date, location, uav_name,
                      weather, sorties, description, end_date, start_date, fly_time, camera_name):
        """
        保存项目
        """
        full_name = request.user.full_name
        is_exist, reason = services.is_project_already_exist(name, company, full_name)
        if is_exist:
            raise exc.ValidationError(reason)

        py = Pinyin()
        project_model = models.Project
        project = project_model(
            name=name,
            company=company,
            weather=weather,
            sorties=sorties,
            end_date=end_date,
            location=location,
            fly_time=fly_time,
            start_date=start_date,
            description=description,
            operation_date=operation_date,
            slug=py.get_pinyin(name).replace('-', '_'),
            project_type=models.ProjectType.objects.get(id=1),
            owner=get_user_model().objects.get(full_name=full_name),
            uav=apps.get_model("equipments", "UAV").objects.get(name=uav_name),
            camera=apps.get_model("equipments", "Camera").objects.get(name=camera_name),
        )
        try:
            project.save()

            "初始化项目角色"
            for role in services.role_list:
                models.Role.objects.create(name=role, slug=role, permissions=json.dumps(services.permission[role]),
                                           project=project)

        except Exception as e:
            raise exc.ValidationError(_("project register failed"))

        signals.project_registered_signal.send(sender=project.__class__, project=project)

        return project

    def _updata_project(self, project_model, ):
        """
        完善部分数据
        """

    def list(self, request, *args, **kwargs):
        """
        群查
        """
        owner_id = request.query_params.get("owner_id", None)
        project_type_id = request.query_params.get("project_type_id", None)

        if owner_id:
            project_object_list = get_list_or_404(self.get_queryset(), owner__id=owner_id,
                                                  project_type__id=project_type_id)
        else:
            project_object_list = get_list_or_404(self.get_queryset())

        self.check_permissions(request, 'list', project_object_list)

        if project_object_list:
            page = self.paginate_queryset(project_object_list)
            if page is not None:
                serializer = self.get_serializer(page, many=True)
                return self.get_paginated_response(serializer.data)
            else:
                serializer = self.get_serializer(project_object_list, many=True)

            return response.Ok(serializer.data)
        else:
            return response.Ok({"message": "Have no project"})

    def create(self, request, *args, **kwargs):
        """
        创建项目
        """
        self.check_permissions(request, 'create', None)
        "验证数据"
        try:
            data = parse_data(request.data, cls=validators.ProjectValidator)
            project = self._save_project(request, **data)
        except exc.ParseError as e:
            raise exc.BadRequest(e.detail)

        serializer = self.get_serializer(project)
        return response.Created(serializer.data)

    def destroy(self, request, *args, **kwargs):
        """
        销毁项目
        """
        project_object = get_object_or_404(self.queryset, **kwargs)
        self.check_permissions(request, "destroy", project_object)
        project_object.delete()
        return response.NoContent()

    def retrieve(self, request, *args, **kwargs):
        """
        单查项目(GET)
        """
        project_object = get_object_or_404(self.queryset, **kwargs)
        self.check_permissions(request, 'retrieve', project_object)
        serializer = self.get_serializer(project_object)
        return response.Ok(serializer.data)

    def partial_update(self, request, *args, **kwargs):
        """
        更新项目
        """
        project_model = get_object_or_404(self.queryset, **kwargs)
        self.check_permissions(request, 'partial_update', None)
        "验证数据"
        try:
            data = parse_data(request.data, cls=validators.ProjectValidator)
            project = self._updata_project(project_model=project_model, **data)
        except exc.ParseError as e:
            raise exc.BadRequest(e.detail)

        serializer = self.get_serializer(project)
        return response.Created(serializer.data)

    @detail_route(methods=["POST"])
    def add_map(self, request, pk=None):
        """
        添加项目地图
        """
        project = get_object_or_404(self.queryset, pk=pk)
        self.check_permissions(request, 'add_map', project)

        map_path = request.data.get('map_path', None)
        try:
            project.map_path = map_path
            project.save()
        except exc.ValidationError as e:
            raise exc.BadRequest(e.detail)

        serializer = self.get_serializer(project)
        return response.Ok(serializer.data)

    @detail_route(methods=["POST"])
    def add_report(self, request, pk=None):
        """
        添加项目报告
        """
        project = get_object_or_404(self.queryset, pk=pk)
        self.check_permissions(request, 'add_report', project)

        report_path = request.data.get('report_path', None)
        try:
            project.report_path = report_path
            project.save()
        except exc.ValidationError as e:
            raise exc.BadRequest(e.detail)

        serializer = self.get_serializer(project)
        return response.Ok(serializer.data)

    @detail_route(methods=["GET"])
    def get_project_progress(self, request, pk):
        """
        获取项目数量
        """

        project = get_object_or_404(self.queryset, pk=pk)

        ret = {'analysis_progress': project.analysis_progress, 'view_status': project.view_status,
               'analysis_status': project.analysis_status}

        return response.Ok(ret)


class ProjectAdminViewSet(viewsets.ModelViewSet):
    """
    项目管理视图
    """
    queryset = models.Project.objects.all()
    "序列化"
    serializer_class = serializers.ProjectAdminSerializer
    "权限"
    permission_classes = (permissions.ProjectAdminPermission,)

    def list(self, request, *args, **kwargs):
        """
        群查项目
        """
        project_object_list = self.get_queryset()
        self.check_permissions(request, 'list', None)

        page = self.paginate_queryset(project_object_list)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        else:
            serializer = self.get_serializer(project_object_list, many=True)

        return response.Ok(serializer.data)

    @detail_route(methods=["GET"])
    def get_project_number(self, request, pk):
        """
        获取项目数量
        """
        project_number = self.queryset.count()

        return response.Ok({"projectNumber": project_number})
